package net.lwf.file.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.lwf.exception.ExceptionUtil;

import org.apache.commons.lang.StringUtils;


public class FileFolderReader {
	private static String FILES_DIRECTORY = "C:/downloads/common";
	
	/**
	  * Demonstrate use.
	  * 
	  * @param aArgs - <tt>aArgs[0]</tt> is the full name of an existing 
	  * directory that can be read.
	  */
	  public static void main(String[] aArgs) {
		File startingDirectory = new File(FILES_DIRECTORY);
		List files = getFileListing(startingDirectory);
		for (int i = 0; i < files.size(); i++) {
			System.out.println(files.get(i));
		}
		
		System.out.println(".....................................................................................");
		Map mapfiles = getMappedFileListing(startingDirectory);
		Iterator iter = mapfiles.entrySet().iterator();
		while(iter.hasNext()) {
			Map.Entry mapentry = (Map.Entry) iter.next();
			String directory = (String) mapentry.getKey();
			System.out.println("===> Directory: " + directory);
			files = (List) mapentry.getValue();
			for(int i=0; i<files.size(); i++) {
				System.out.println(files.get(i));
			}
		}		
		
		
	}

	/**
	 * Recursively walk a directory tree and return a List of all
	 * Files found; the List is sorted using File.compareTo().
	 *
	 * @param aStartingDir is a valid directory, which can be read.
	 */
	public static List getFileListing(File aStartingDir) {
		validateDirectory(aStartingDir);
		List result = getFileListingNoSort(aStartingDir);
		Collections.sort(result);
		return result;
	}
	
	public static List<FileNamePath> getSortedFileListing(File aStartingDir, String filter)
			throws FileNotFoundException {
		validateDirectory(aStartingDir);
		List<FileNamePath> result = getFileListing(aStartingDir, filter);
		//Collections.sort(result);
		return result;
	}

	// PRIVATE //
	private static List getFileListingNoSort(File aStartingDir) {
		List result = new ArrayList();
		File[] filesAndDirs = aStartingDir.listFiles();
		List filesDirs = Arrays.asList(filesAndDirs);
		for (int i = 0; i < filesDirs.size(); i++) {
			File file = (File) filesDirs.get(i);
			
			String filename = file.getPath();
			int pos = filename.indexOf("image");
			String correctedimage = filename.substring(pos);

			if(filterImage(correctedimage)) {
				result.add(correctedimage); //always add, even if directory	
			}
			
			
			if (!file.isFile()) {
				//must be a directory
				//recursive call!
				List deeperList = getFileListingNoSort(file);
				result.addAll(deeperList);
			}
		}
		return result;
	}
	
	public static List<FileNamePath> getFileListing(File aStartingDir, String filter)
			throws FileNotFoundException {
		List<FileNamePath> result = new ArrayList<FileNamePath>();
		File[] filesAndDirs = aStartingDir.listFiles();
		List<File> filesDirs = Arrays.asList(filesAndDirs);
		for (int i = 0; i < filesDirs.size(); i++) {
			File file = (File) filesDirs.get(i);
			String filename = file.getPath();
			String filepath = file.getParent();
			int pos = filename.indexOf("/eclipse/workspace");
			
			//System.err.println("================ File name  ........." + filename + "; Parent: " + file.getParent() + "       Position: " + pos);
			if(filter != null) {
				if(filter(filename, filter)) {
					//System.err.println("================ Valid files ........." + filename);
					FileNamePath namepath = new FileNamePath();
					namepath.setPath(filepath);
					
					//System.err.println("================> Position: " + pos);
					if(!filename.equals(filepath)) {
						namepath.setName(StringUtils.replace(filename, filepath + "/", ""));
					}
					result.add(namepath); 	
				}

			}

			if (!file.isFile()) {
				//must be a directory
				//recursive call!
				List<FileNamePath> deeperList = getFileListing(file, filter);
				result.addAll(deeperList);
			}

		}
		return result;
	}
	
	private static boolean filterImage(String image) {
		if(image.indexOf("Thumbs.db") != -1) {
			return false;
		}
		if(image.indexOf(".") == -1) {
			return false;
		}
		
		return true;
	}
	
	private static boolean filter(String filename, String filterstring) {
		
		if(filename.indexOf(filterstring) != -1) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * Recursively walk a directory tree and return a List of all
	 * Files found; the List is sorted using File.compareTo().
	 *
	 * @param aStartingDir is a valid directory, which can be read.
	 */
	public static Map getMappedFileListing(File aStartingDir) {
		validateDirectory(aStartingDir);
		Map mapfiles = new HashMap();
		getMappedFileListing(aStartingDir, mapfiles);
		return mapfiles;
	}

	// PRIVATE //
	private static void getMappedFileListing(File aStartingDir, Map mapfiles) {
		List result = new ArrayList();
		File[] filesAndDirs = aStartingDir.listFiles();
		List filesDirs = Arrays.asList(filesAndDirs);
		List base = new ArrayList();
		for (int i = 0; i < filesDirs.size(); i++) {
			
			File file = (File) filesDirs.get(i);
			result.add(file); //always add, even if directory
			if (!file.isFile()) {
				//must be a directory
				//recursive call!
				List deeperList = getFileListingNoSort(file);
				//result.addAll(deeperList);
				mapfiles.put(file.getName(), deeperList);
			}
			else {
				base.add(file.getName());
				mapfiles.put("basedirectory", base);
			}
		}
		//return result;
	}
	

	/**
	 * Directory is valid if it exists, does not represent a file, and can be read.
	 */
	private static void validateDirectory(File aDirectory) {
		if (aDirectory == null) {
			IllegalArgumentException iaex = new IllegalArgumentException(".... Directory should not be null.");
			ExceptionUtil.logAndThrowException(FileFolderReader.class, iaex);
		}
		if (!aDirectory.exists()) {
			FileNotFoundException fnfex = new FileNotFoundException("Directory does not exist: " + aDirectory);
			ExceptionUtil.logAndThrowException(FileFolderReader.class, fnfex);
		}
		if (!aDirectory.isDirectory()) {
			IllegalArgumentException iaex = new IllegalArgumentException(aDirectory + " is not a directory....");
			ExceptionUtil.logAndThrowException(FileFolderReader.class, iaex);
		}
		if (!aDirectory.canRead()) {
			IllegalArgumentException iaex = new IllegalArgumentException(aDirectory + ", directory can not be read....");
			ExceptionUtil.logAndThrowException(FileFolderReader.class, iaex);
		}
	}
	
}
